home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QRZ! Ham Radio 8
/
QRZ Ham Radio Callsign Database - Volume 8.iso
/
pc
/
files
/
t_unix
/
bs941029.tgz
/
bbsx-941029.tar
/
bbsx
/
bbs_cmds.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-10-29
|
56KB
|
2,117 lines
#define _HPUX_SOURCE
#include <sys/types.h>
#include <stdio.h>
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <termios.h>
#include <time.h>
#include <unistd.h>
#include <ndbm.h>
#include <fnmatch.h>
#include "bbs.h"
#include "buildsaddr.h"
#include "strdup.h"
#include "callvalid.h"
#include "lockfile.h"
/*---------------------------------------------------------------------------*/
const struct cmdtable cmdtable[] = {
"!", shell_command, 0, USER,
"?", help_command, 0, USER,
"ALIAS", alias_command, 0, USER,
"BYE", bye_command, 0, USER,
"CHANGE", change_command, 3, ROOT,
"DELETE", delete_command, 2, USER,
"DESTROY", destroy_command, 2, ROOT,
"DIR", dir_command, 0, USER,
"DISCONNECT", disconnect_command, 0, USER,
"ERASE", delete_command, 2, USER,
"EXIT", quit_command, 0, USER,
"F", f_command, 2, MBOX,
"HELP", help_command, 0, USER,
"HIDE", hide_command, 2, ROOT,
"INFO", info_command, 0, USER,
"KILL", delete_command, 2, USER,
"LIST", list_command, 2, USER,
"MAIL", mail_command, 3, USER,
"MOVE", move_command, 2, USER,
"MYBBS", mybbs_command, 2, USER,
"PRINT", read_command, 2, USER,
"QUIT", quit_command, 0, USER,
"READ", read_command, 2, USER,
"REPLY", reply_command, 2, USER,
"RESPOND", reply_command, 2, USER,
"SB", send_command, 2, MBOX,
"SEND", send_command, 2, USER,
"SET", set_command, 0, USER,
"SHELL", shell_command, 0, USER,
"SOURCE", source_command, 2, USER,
"SP", send_command, 2, MBOX,
"STATUS", status_command, 0, USER,
"TELL", tell_command, 3, USER,
"TYPE", read_command, 2, USER,
"UNDELETE", undelete_command, 2, USER,
"UNERASE", undelete_command, 2, USER,
"UNSET", unset_command, 2, USER,
"VERSION", status_command, 0, USER,
"WRITE", write_command, 3, USER,
"XCRUNCH", xcrunch_command, 0, ROOT,
"XSCREEN", xscreen_command, 0, ROOT,
"[", sid_command, 0, MBOX,
0, unknown_command, 0, USER
};
/*---------------------------------------------------------------------------*/
void alias_command(int argc, char **argv)
{
struct aliastable *p, *new;
char orig[256], alias[256];
char *cp;
char *errstr = "Syntax error. Type ? ALIAS for help.";
int i;
if (level == MBOX) return;
if (argc==1) {
p=alias_table;
while (p) {
if (!p->is_std) printf("alias: %s maped to: %s\n",p->orig, p->alias);
p=p->next;
}
return;
} else
{
if (argc < 3 || *argv[2] != '=') {
printf("%s\n",errstr);
return;
}
strcpy(orig,argv[1]);
*alias=0;
for(i=3; i < argc; i++) {
if(i > 3) strcat(alias," ");
strcat(alias,argv[i]);
}
insert_alias(orig, alias, 0, 0);
}
}
/*---------------------------------------------------------------------------*/
void bye_command(int argc, char **argv)
{
puts("BBS terminated.");
if (level != MBOX) free(alias_table);
exit(0);
}
/*---------------------------------------------------------------------------*/
void change_command(int argc, char **argv)
{
int i;
int mesg;
char line[256];
struct index index;
int found = 0;
int lifetime;
for (i = 2; i < argc; i++) {
if ((mesg = atoi(argv[i])) > 0 && get_index(mesg, &index) &&
!(index.flags & DELETED)) {
found = 1;
strlwc(argv[1]);
if (!strcmp("#", argv[1]) || !strncmp(argv[1],"lifetime",strlen(argv[1]))) {
lifetime = ((index.lifetime_h << 8) & 0xff00) + (index.lifetime_l & 0xff) - 1;
printf("Message #%d Lifetime ", mesg);
if (lifetime >= 0) {
printf("[%d] : ", lifetime);
} else {
printf("[expired] : ");
}
*line=0;
if (!getstring(line)) exit(1);
if (*line) {
if (!Strncasecmp(line,"expired",strlen(line)))
lifetime = -1;
else
lifetime = Atoi(line);
index.lifetime_h = (lifetime + 1) >> 8;
index.lifetime_l = (lifetime + 1);
}
}else
if (!strcmp("$", argv[1]) || !strncmp(argv[1],"bid",strlen(argv[1]))) {
printf("Message #%d BID [%s] : ", mesg, index.bid);
*line=0;
if(!getstring(line)) exit(1);
line[LEN_BID] = 0;
if (*line) {
strupc(line);
strcpy(index.bid, line);
}
}else
if (!strcmp(">", argv[1]) || !strncmp(argv[1],"to",strlen(argv[1]))) {
printf("Message #%d TO [%s] : ", mesg, index.to);
*line=0;
if(!getstring(line)) exit(1);
line[LEN_TO] = 0;
if (*line) {
strupc(line);
strcpy(index.to, line);
}
}else
if (!strcmp("<", argv[1]) || !strncmp(argv[1],"from",strlen(argv[1]))) {
printf("Message #%d FROM [%s] : ", mesg, index.from);
*line=0;
if(!getstring(line)) exit(1);
line[LEN_FROM] = 0;
if (*line) {
strupc(line);
if (callvalid(line)) {
strcpy(index.from, line);
} else
{
printf("%s is not a valid call.\n");
}
}
}else
if (!strcmp("@", argv[1]) || !strncmp(argv[1],"at",strlen(argv[1]))) {
printf("Message #%d AT [%s] : ", mesg, index.at);
*line=0;
if(!getstring(line)) exit(1);
line[LEN_AT] = 0;
if (*line) {
strupc(line);
strcpy(index.at, line);
}
}else
if (!Strncasecmp(argv[1],"Subject",strlen(argv[1]))) {
printf("Message #%d Subject [%s] : ", mesg, index.subject);
*line=0;
if(!getstring(line)) exit(1);
line[LEN_SUBJECT] = 0;
if (*line) {
strcpy(index.subject, line);
}
}else
{
printf("%s ? What's that ?\n", argv[1]);
return;
}
if (lseek(fdindex, -sizeof(struct index), SEEK_CUR) < 0) halt();
if (write(fdindex, &index, sizeof(struct index)) !=
sizeof(struct index)) halt();
}
}
if (!found) {
printf("No message found.\n");
}
}
/*---------------------------------------------------------------------------*/
void delete_command(int argc, char **argv)
{
int i;
int mesg;
char line[256];
struct index index;
struct mail *mail;
int max_mesg;
int found = 0;
max_mesg = get_highest_mesg(argc,argv);
for (mesg = get_lowest_mesg(argc,argv); mesg <= max_mesg; mesg++)
if (mesg_in_command(argc, argv, mesg, &index) &&
!(index.flags & DELETED)) {
found = 1;
if (level == ROOT ||
calleq(index.from, user.name) ||
calleq(index.to, user.name)) {
index.date = time((long *) 0);
if (strcmp(index.at, Myhostname) && level != ROOT) {
mail=alloc_mail();
strcpy(mail->to,"E@THEBOX");
strcpy(mail->orig_to,"E@THEBOX");
strcpy(mail->from, user.name);
*mail->bid=0;
strcpy(mail->subject,index.bid);
route_mail(mail);
free_mail(mail);
get_index(mesg,&index);
}
strcpy(index.to,"B");
strcpy(index.at,Myhostname);
if (lseek(fdindex, -sizeof(struct index), SEEK_CUR) < 0) halt();
if (write(fdindex, &index, sizeof(struct index)) !=
sizeof(struct index)) halt();
if (level == ROOT )
printf("Message %d is now in Backuparea.\n", mesg);
else
printf("Message %d deleted.\n", mesg);
} else
printf("Message %d not deleted: Permission denied.\n", mesg);
}
if (!found) {
printf("No message found.\n");
}
}
/*---------------------------------------------------------------------------*/
void destroy_command(int argc, char **argv)
{
int i;
int mesg;
struct index index;
int max_mesg;
int found = 0;
max_mesg = get_highest_mesg(argc,argv);
for (mesg = get_lowest_mesg(argc,argv); mesg <= max_mesg; mesg++)
if (mesg_in_command(argc, argv, mesg, &index) &&
!(index.flags & DELETED)) {
found = 1;
if (level == ROOT ||
calleq(index.from, user.name) ||
calleq(index.to, user.name)) {
if (unlink(getfilename(mesg))) halt();
index.flags = index.flags | DELETED;
if (lseek(fdindex, -sizeof(struct index), SEEK_CUR) < 0) halt();
if (write(fdindex, &index, sizeof(struct index)) != sizeof(struct index)) halt();
printf("Message %d deleted.\n", mesg);
} else
printf("Message %d not deleted: Permission denied.\n", mesg);
}
if (!found) {
printf("No message found.\n");
}
}
/*---------------------------------------------------------------------------*/
void dir_command(int argc, char **argv)
{
int n, cmp, i;
struct dir_entry *head, *curr, *prev;
struct index *pi, index[1000];
int match = 0;
head = 0;
cmp = 0;
if (lseek(fdindex, 0L, SEEK_SET)) halt();
for (; ; ) {
n = read(fdindex, pi = index, 1000 * sizeof(struct index)) / sizeof(struct index);
if (n < 1) break;
for (; n; n--, pi++) {
if (argc > 1) {
match = 0;
for(i=1; i < argc && !match; i++) {
match = (fnmatch(argv[i], pi->to, FNM_CASEFOLD) != FNM_NOMATCH);
}
}
else match = 1;
if (read_allowed(pi) && match)
for (prev = 0, curr = head; ; ) {
if (!curr) {
curr = malloc(sizeof(*curr));
curr->left = curr->right = 0;
curr->count = 1;
strcpy(curr->to, pi->to);
if (!prev)
head = curr;
else if (cmp < 0)
prev->left = curr;
else
prev->right = curr;
break;
}
if (!(cmp = strcmp(pi->to, curr->to))) {
curr->count++;
break;
}
prev = curr;
curr = (cmp < 0) ? curr->left : curr->right;
}
}
}
dir_column = 0;
dir_print(head);
if (!stopped && (dir_column % 5)) putchar('\n');
}
/*---------------------------------------------------------------------------*/
void disconnect_command(int argc, char **argv)
{
free(alias_table);
if (user.seq < highest_on_start) user.seq = highest_on_start;
if (level != MBOX) {
put_seq();
free(alias_table);
}
puts("Disconnecting...");
kill(0, 1);
exit(0);
}
/*---------------------------------------------------------------------------*/
void f_command(int argc, char **argv)
{
int do_not_exit;
struct index index;
int count=0;
do_not_exit=doforward;
forward_mail();
get_seq();
if (!get_index(user.seq, &index))
if (lseek(fdindex, 0L, SEEK_SET)) halt();
while (read(fdindex, &index, sizeof(struct index)) == sizeof(struct index)) {
if (!(count % 10)) {
forward_mail();
}
count++;
if (!(index.flags & DELETED) &&
index.mesg > user.seq &&
!calleq(index.at, myhostname) &&
!host_in_header(getfilename(index.mesg), user.name)) {
forward_message(&index, getfilename(index.mesg), index.at, 0);
do_not_exit = 1;
}
if (user.seq < index.mesg) {
user.seq = index.mesg;
put_seq();
}
}
if (!do_not_exit) exit(0);
close(fdseq);
putchar('F');
}
/*---------------------------------------------------------------------------*/
void help_command(int argc, char **argv)
{
FILE *fp;
char line[1024];
int i;
int state;
struct aliastable *p;
if (argc < 2) {
puts("Commands may be abbreviated. Commands are:");
i=0;
p=alias_table;
while(p) {
if (level >= p->level && p->is_std)
printf((i++ % 6) < 5 ? "%-13s" : "%s\n", p->orig);
p=p->next;
}
if (i % 6) putchar('\n');
return;
}
if (!(fp = fopen(helpfile, "r"))) {
puts("Sorry, cannot open help file.");
return;
}
if (!Strcasecmp(argv[1], "all")) {
while (!stopped && fgets(line, sizeof(line), fp))
if (*line != '^') fputs(line, stdout);
} else {
state = 0;
while (!stopped && fgets(line, sizeof(line), fp)) {
strtrim(line);
if (state == 0 && *line == '^' && !Strcasecmp(line + 1, argv[1]))
state = 1;
if (state == 1 && *line != '^')
state = 2;
if (state == 2) {
if (*line == '^') break;
puts(line);
}
}
if (!stopped && state < 2)
printf("Sorry, there is no help available for '%s'.\n", argv[1]);
}
fclose(fp);
}
/*---------------------------------------------------------------------------*/
void hide_command(int argc, char **argv)
{
int i;
int mesg;
char line[90];
struct index index;
int max_mesg;
int found = 0;
max_mesg = get_highest_mesg(argc,argv);
for (mesg = get_lowest_mesg(argc,argv); mesg <= max_mesg; mesg++)
if (mesg_in_command(argc, argv, mesg, &index) &&
!(index.flags & DELETED)) {
found = 1;
strcpy(index.to,"A");
strcpy(index.at,myhostname);strupc(index.at);
if (lseek(fdindex, -sizeof(struct index), SEEK_CUR) < 0) halt();
if (write(fdindex, &index, sizeof(struct index)) != sizeof(struct index)) halt();
printf("Message %d is now hidden.\n", mesg);
}
if (!found) {
printf("No message found.\n");
}
}
/*---------------------------------------------------------------------------*/
void info_command(int argc, char **argv)
{
FILE *fp;
int c;
if (!(fp = fopen(infofile, "r"))) {
puts("Sorry, cannot open info file.");
return;
}
while (!stopped && (c = getc(fp)) != EOF) putchar(c);
fclose(fp);
}
/*---------------------------------------------------------------------------*/
#define nextarg(name) \
if (++i >= argc) { \
errors++; \
printf(errstr, name); \
return; \
}
#define MAX_MESG 999999
void list_command(int argc, char **argv)
{
char *at = 0;
char *bid = 0;
char *errstr = "The %s option requires an argument. Type ? LIST for help.\n";
char *from = 0;
char *subject = 0;
char *to = 0;
int count = MAX_MESG;
int found = 0;
int i;
int max = MAX_MESG;
int min = 1;
int update_seq = 0;
size_t len;
struct index index;
char buffer[LEN_SUBJECT+6];
static struct termio save;
int nr_list;
if (interface_type != wampes)
count = 1;
nr_list = max_list;
for (i = 1; i < argc; i++) {
len = strlen(strlwc(argv[i]));
if (!strcmp("$", argv[i]) || !strncmp("bid", argv[i], len)) {
nextarg("BID");
bid = strupc(argv[i]);
} else if (!strcmp("<", argv[i]) || !strncmp("from", argv[i], len)) {
nextarg("FROM");
from = strupc(argv[i]);
} else if (!strcmp(">", argv[i]) || !strncmp("to", argv[i], len)) {
nextarg("TO");
to = strupc(argv[i]);
strcpy(last_board,to);
} else if (!strcmp("@", argv[i]) || !strncmp("at", argv[i], len)) {
nextarg("AT");
at = strupc(argv[i]);
} else if (!strcmp("+", argv[i]) && (interface_type != wampes)) {
nextarg("+");
count = Atoi(argv[i]);
nr_list = MAX_MESG;
} else if (!strcmp("-", argv[i])) {
if (Atoi(argv[i-1]) && !Atoi(argv[i+1])) { /* z.B.: 3- */
min = Atoi(argv[i-1]);
max = MAX_MESG;
nr_list = MAX_MESG;
} else
if (!Atoi(argv[i-1]) && Atoi(argv[i+1])) { /* z.B.: -3 */
nextarg("-");
min = 0;
max = Atoi(argv[i]);
nr_list = MAX_MESG;
} else
if (Atoi(argv[i-1]) && Atoi(argv[i+1])) { /* z.B.: 3-4 */
min = Atoi(argv[i-1]);
nextarg("-");
max = Atoi(argv[i]);
nr_list = MAX_MESG;
}
} else if (!strncmp("count", argv[i], len)) {
nextarg("COUNT");
count = Atoi(argv[i]);
nr_list = MAX_MESG;
} else if (!strncmp("all", argv[i], len)) {
if (i+1 == argc)
to = strupc(argv[i]);
nr_list = MAX_MESG;
} else if (!strncmp("new", argv[i], len)) {
min = user.seq + 1;
update_seq = (argc == 2 && level == USER);
} else if (!strncmp("max", argv[i], len)) {
nextarg("MAX");
max = Atoi(argv[i]);
} else if (!strncmp("min", argv[i], len)) {
nextarg("MIN");
min = Atoi(argv[i]);
nr_list = MAX_MESG;
} else if (!strncmp("subject", argv[i], len)) {
nextarg("SUBJECT");
subject = argv[i];
nr_list = MAX_MESG;
} else if (Atoi(argv[i])) {
min = max = Atoi(argv[i]);
} else {
to = strupc(argv[i]);
strcpy(last_board,to);
}
}
if (is_tell_user)
if (count && count > 25)
count = 25;
if ((level == USER) && (!last_board[1])) {
*last_board = 0;
}
if (interface_type == wampes) {
if (!to) *last_board= 0;
} else
if (!count)
if (*last_board && !to)
to=strupc(last_board);
else
if (!*last_board && !to) {
strcpy(last_board,user.name);
to = strupc(last_board);
}
ioctl(0,TCGETA, &save);
save.c_cc[VINTR] = escape_char;
ioctl(0,TCSETA, &save);
if (to) {
strcpy(buffer,to);
getalias(buffer);
if (strcmp(to, buffer)) {
printf("\n *** WARNING ***\n");
printf(" *** Board %s is not available. Bulletins are stored in %s. ***\n\n\n", to, buffer);
strcpy(to, buffer);
}
}
if (lseek(fdindex, -sizeof(struct index), SEEK_END) >= 0) {
for (; ; ) {
if (stopped) {
*last_board = 0;
return;
}
if (read(fdindex, &index, sizeof(struct index)) != sizeof(struct index)) halt();
if (index.mesg < min) break;
if (index.mesg <= max &&
read_allowed(&index) &&
(!bid || !strcmp(index.bid, bid)) &&
(!from || !strcmp(index.from, from)) &&
(!to || !strcmp(index.to, to)) &&
(!at || !strcmp(index.at, at)) &&
(!subject || strcasepos(index.subject, subject))) {
if (!found) {
puts(" Msg# Size To @ BBS From Date Subject");
found = 1;
} else
found++;
if (index.flags & BINARY) {
sprintf(buffer,"(BIN) %s",index.subject);
} else
{
strcpy(buffer,index.subject);
}
printf("%6d %5ld %-8s%c%-8s %-8s %-7.7s %.31s\n",
index.mesg,
index.size,
index.to,
*index.at ? '@' : ' ',
index.at,
index.from,
timestr(index.date),
buffer);
if (update_seq && user.seq < index.mesg) {
user.seq = index.mesg;
}
if (--count <= 0) break;
if (is_tell_user && found == 50) break;
}
if (lseek(fdindex, -2L * sizeof(struct index), SEEK_CUR) < 0) break;
if (--nr_list <=0) break;
}
}
if (!found) {
puts(update_seq ?
"No new messages since last LIST NEW command." :
"No matching message found.");
*last_board = 0;
}
save.c_cc[VINTR] = orig_escape;
ioctl(0,TCSETA, &save);
}
#undef MAX_MESG
#undef nextarg
/*---------------------------------------------------------------------------*/
#define nextarg(name) \
if (++i >= argc) \
{ \
errors++; \
printf(errstr, name) ; \
free_mail(mail); \
return; \
}
void mail_command(int argc, char **argv)
{
char *errstr = "The %s option requires an argument. Type ? MAIL for help.\n";
FILE *fp;
char buffer[1024];
char to[512];
int mesg;
struct index index;
struct mail *mail;
int i;
int found = 0;
if (argc < 3) {
printf("Syntax error. Type ? MAIL for help.\n");
return;
}
strcpy(to,argv[1]);
for(i = 2; i < argc; i++) {
if (!strcmp("@", argv[i])) {
nextarg("@");
strcat(to,"@");
strcat(to, argv[i]);
} else
if ((mesg = Atoi(argv[i])) > 0 && get_index(mesg, &index) &&
read_allowed(&index)) {
found = 1;
if (level == ROOT ||
calleq(index.from, user.name)) {
mail = alloc_mail();
if (level == ROOT )
strcpy(mail->from, index.from);
else
strcpy(mail->from, user.name);
strcpy(mail->to, to);
strcpy(mail->orig_to, to);
strcpy(mail->subject, index.subject);
mail->lifetime= index.lifetime_h << 8 + index.lifetime_l;
*mail->bid = 0;
*mail->mid = 0;
strlwc(mail->to);
strlwc(mail->orig_to);
if (!(fp = fopen(getfilename(mesg), "r"))) halt();
while (fgets(buffer, sizeof(buffer), fp)) {
buffer[strlen(buffer)-1] = 0;
append_line(mail, buffer);
}
printf("Sending message to %s.\n", mail->to);
route_mail(mail);
}
else
printf("Message: %s - permission denied.\n",argv[i]);
}
}
if (!found) {
printf("No message found.\n");
}
return;
}
#undef nextarg
/*---------------------------------------------------------------------------*/
#define nextarg(name) \
if (++i >= argc) { \
errors++; \
printf(errstr, name); \
return; \
}
void move_command(int argc, char **argv)
{
char *errstr = "The %s option requires an argument. Type ? MOVE for help.\n";
int i,len;
int mesg;
struct index index;
char forward[80];
int found = 0;
*forward = 0;
for (i = 1; i < argc; i++){
len = strlen(strupc(argv[i]));
if (!strcmp("TO", argv[i])) {
nextarg("TO");
strcpy(forward,strupc(argv[i]));
} else if (!strcmp(">", argv[i])) {
nextarg("TO");
strcpy(forward,strupc(argv[i]));
}
getalias(forward);
if ((mesg = Atoi(argv[i])) > 0 && get_index(mesg, &index) &&
!(index.flags & DELETED)) {
found = 1;
if (level == ROOT ||
calleq(index.from, user.name) ||
calleq(index.to, user.name)) {
if (lseek(fdindex, -sizeof(struct index), SEEK_CUR) < 0) halt();
if (!strcmp(forward,""))
{
puts("No forward-area defined!");
return ;
}
if (strlen(forward) == 1 && level != ROOT)
{
printf("Message %d not moved: Permission denied.\n", mesg);
return ;
}
else {
strcpy(index.to,forward);
if (!forward_allowed(&index,myhostname)) {
printf("Message %d not moved: Permission denied.\n", mesg);
return ;
}
if (write(fdindex, &index, sizeof(struct index)) !=
sizeof(struct index)) halt();
printf("Message %d moved.\n", mesg);
}
} else
printf("Message %d not moved: Permission denied.\n", mesg);
}
else
if(Atoi(argv[i]))
printf("No such message: '%s'.\n", argv[i]);
}
if (!found) {
printf("No message found.\n");
}
}
#undef nextarg
/*---------------------------------------------------------------------------*/
void mybbs_command(int argc, char **argv)
{
struct mail *mail;
if (!callvalid(strupc(argv[1]))) {
printf("Invalid call '%s'.\n", argv[1]);
return;
}
mail = alloc_mail();
strcpy(mail->from, user.name);
strcpy(mail->to, "m@thebox");
strcpy(mail->orig_to,"m@thebox");
sprintf(mail->subject, "%s %ld", argv[1], time((long *) 0));
append_line(mail, "");
printf("Setting MYBBS to %s.\n", argv[1]);
route_mail(mail);
}
/*---------------------------------------------------------------------------*/
void quit_command(int argc, char **argv)
{
if (user.seq < highest_on_start) user.seq = highest_on_start;
if (level != MBOX) {
put_seq();
free(alias_table);
}
puts("BBS terminated.");
exit(0);
}
/*---------------------------------------------------------------------------*/
void read_command(int argc, char **argv)
{
FILE *fp;
char *p;
char buf[1024];
char path[1024];
int i;
int inheader;
int mesg;
struct index index;
struct log log;
static struct termio save;
int max_mesg;
int bytes=0;
int fdlog;
int found = 0;
struct tm *tm;
long now;
char logfile[80];
ioctl(0,TCGETA, &save);
save.c_cc[VINTR] = escape_char;
ioctl(0,TCSETA, &save);
now = time(0L);
tm=gmtime(&now);
sprintf(logfile,"%s%02d%02d.log",LOGFILE,tm->tm_year, tm->tm_mon);
max_mesg = get_highest_mesg(argc,argv);
for (mesg = get_lowest_mesg(argc,argv); mesg <= max_mesg; mesg++)
if (mesg_in_command(argc, argv, mesg, &index) && read_allowed(&index)) {
found = 1;
if (!(fp = fopen(getfilename(mesg), "r"))) halt();
if (log_reading && level == USER) bytes = 0;
printf("\nMsg# %d To: %s%s%s From: %s Date: %s\n",
index.mesg,
index.to,
*index.at ? " @" : "",
index.at,
index.from,
timestr(index.date));
if (*index.subject) printf("Subject: %s\n", index.subject);
if (*index.bid) printf("Bulletin ID: %s\n", index.bid);
if (level != MBOX) printf("\n");
fflush(stdout);
*path = 0;
inheader = 1;
while (fgets(buf, sizeof(buf), fp)) {
if (stopped) {
fclose(fp);
return;
}
if (inheader) {
if (p = get_host_from_header(buf)) {
strcat(path, *path ? "!" : "Path: ");
strcat(path, p);
continue;
}
if (*path) puts(path);
inheader = 0;
}
#ifdef BOXBIN
if (!strncmp(buf,"#UUENCODE#",10) && binary_allowed)
{
sscanf(buf,"#UUENCODE%s",path);
if (uudecode(fp,path)) halt();
fclose(fp);
save.c_cc[VINTR] = orig_escape;
ioctl(0,TCSETA, &save);
return;
}
#endif
fputs(buf, stdout);
if (log_reading) {
bytes += strlen(buf);
bytes++;
}
}
putchar('\n');
fclose(fp);
if(log_reading && bytes && level == USER) {
strcpy(log.to, index.to);
log.bytes=bytes;
log.uid = user.uid;
log.time = time(0L);
if ((fdlog = lock_file(LOCKFILE, 0)) < 0) halt();
if (lseek(fdlog, 0L, SEEK_END) < 0) halt();
if (write(fdlog, &log, sizeof(struct log)) != sizeof(struct log)) halt();
close(fdlog);
}
}
save.c_cc[VINTR] = orig_escape;
ioctl(0,TCSETA, &save);
if (!found) {
printf("No message found.\n");
}
}
/*---------------------------------------------------------------------------*/
void reply_command(int argc, char **argv)
{
FILE *fp;
char *host;
char *mesgstr;
char *p;
static char line[1024];
int all;
int i;
int mesg;
struct index index;
static struct mail *mail;
mesg = all = 0;
mesgstr = 0;
for (i = 1; i < argc; i++)
if (!Strcasecmp(argv[i], "all"))
all = 1;
else
mesg = Atoi(mesgstr = argv[i]);
if (!mesgstr) {
puts("No message number specified.");
return;
}
if (mesg < 1 || !get_index(mesg, &index) || !read_allowed(&index)) {
printf("No such message: '%s'.\n", mesgstr);
return;
}
mail = alloc_mail();
strcpy(mail->from, user.name);
if (all) {
strcpy(mail->to, index.orig_to);
strcpy(mail->orig_to, index.orig_to);
if (*index.at) {
strcat(mail->to, "@");
strcat(mail->to, index.at);
strcat(mail->orig_to, "@");
strcat(mail->orig_to, index.at);
}
} else {
strcpy(mail->to, index.from);
strcpy(mail->orig_to, index.from);
if (!(fp = fopen(getfilename(mesg), "r"))) halt();
for (host = 0; fgets(line, sizeof(line), fp); host = p)
if (!(p = get_host_from_header(line))) break;
fclose(fp);
if (host) {
strcat(mail->to, "@");
strcat(mail->to, host);
strcat(mail->orig_to, "@");
strcat(mail->orig_to, host);
}
}
strlwc(mail->to);
strlwc(mail->orig_to);
for (p = index.subject; ; ) {
while (isspace(uchar(*p))) p++;
if (Strncasecmp(p, "Re:", 3)) break;
p += 3;
}
sprintf(mail->subject, "Re: %s", p);
printf("To: %s\n", mail->to);
printf("Subject: %s\n", mail->subject);
puts("Enter message: (terminate with ^Z or ***END)");
for (; ; ) {
if (!getstring(line)) exit(1);
if (!strncmp(line,"#BIN#",5)) {
#ifdef BOXBIN
mail->bin = 1;
i= send_binary(mail,line);
if( !i ) {
break ;
} else
if (i == 1)
{
mail->bin = 0;
} else
{
free_mail(mail);
return;
}
#else
puts("#NO#");
free_mail(mail);
return;
#endif
}
if (stopped) {
free_mail(mail);
return;
}
if (*line == '\032') break;
if (!Strncasecmp(line, "***end", 6)) break;
append_line(mail, line);
if (strchr(line, '\032')) break;
}
printf("Sending message to %s.\n", mail->to);
route_mail(mail);
}
/*---------------------------------------------------------------------------*/
void shell_command(int argc, char **argv)
{
char command[2048];
int i;
int status;
pid_t pid;
switch (pid = fork()) {
case -1:
puts("Sorry, cannot fork.");
break;
case 0:
setgid(user.gid);
setuid(user.uid);
for (i = open_max() - 1; i >= 3; i--) close(i);
chdir(user.cwd);
*command = 0;
for (i = 1; i < argc; i++) {
if (i > 1) strcat(command, " ");
strcat(command, argv[i]);
}
if (*command)
execl(user.shell, user.shell, "-c", command, (char *) 0);
else
execl(user.shell, user.shell, (char *) 0);
_exit(127);
break;
default:
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
while (waitpid(pid, &status, 0) != pid) ;
signal(SIGINT, interrupt_handler);
signal(SIGQUIT, interrupt_handler);
break;
}
}
/*---------------------------------------------------------------------------*/
#define nextarg(name) \
if (++i >= argc) \
{ \
errors++; \
if (level == MBOX) puts("NO"); else printf(errstr, name) ; \
free_mail(mail); \
return; \
}
void send_command(int argc, char **argv)
{
char *errstr = "The %s option requires an argument. Type ? SEND for help.\n";
char *p;
char at[1024];
static char line[1024];
char path[1024];
int check_header = 1;
int i;
int unique;
static struct mail *mail;
mail = alloc_mail();
*at = *path = 0;
for (i = 1; i < argc; i++)
if (!strcmp("#", argv[i])) {
nextarg("#");
mail->lifetime = Atoi(argv[i]);
} else if (!strcmp("$", argv[i])) {
nextarg("$");
if (level > USER)
strcpy(mail->bid, argv[i]);
} else if (!strcmp("<", argv[i])) {
nextarg("<");
if (level > USER)
strcpy(mail->from, argv[i]);
} else if (!strcmp(">", argv[i])) {
nextarg(">");
strcpy(mail->to, argv[i]);
} else if (!strcmp("@", argv[i])) {
nextarg("@");
strcpy(at, argv[i]);
} else if (*mail->to && subject_in_send) {
if (*argv[i] != '\032') {
if (*mail->subject)
strcat(mail->subject," ");
strcat(mail->subject,argv[i]);
} else i++;
}
else
strcpy(mail->to, argv[i]);
if (!*mail->to) {
errors++;
puts("No recipient specified.");
free_mail(mail);
return;
}
if (level == USER && !mail->to[1]) {
errors++;
puts("Invalid recipient specified.");
free_mail(mail);
return;
}
strcpy(mail->orig_to, mail->to);
if (!callvalid(get_user_from_path(mail->to))){
getalias(mail->to);
if (!send_allowed(mail, at, myhostname)) {
puts((level == MBOX) ? "NO" : "sorry");
free_mail(mail);
return ;
}
}
mail->bin = 0;
if (*at) {
strcat(mail->to, "@");
strcat(mail->to, at);
strcat(mail->orig_to, "@");
strcat(mail->orig_to, at);
}
strlwc(mail->to);
strlwc(mail->orig_to);
if (!*mail->from || level < MBOX) strcpy(mail->from, user.name);
if (*mail->bid) {
mail->bid[LEN_BID] = 0;
strupc(mail->bid);
if ((fdlock = lock_file(LOCKFILE, 0)) < 0) halt();
unique = msg_uniq(mail->bid, mail->mid);
close(fdlock);
if (!unique) {
puts("No");
free_mail(mail);
return;
}
}
if (level == MBOX) {
if ((!strcmp(mail->to,"e@thebox") || !strcmp(mail->to,"m@thebox")) &&
strlen(mail->subject)) {
if (*path) {
strcpy(line, mail->from);
sprintf(mail->from, "%s!%s", path, line);
}
puts("OK");
route_mail(mail);
return;
}
}
if (!*mail->subject) {
puts((level == MBOX) ? "OK" : "Enter subject:");
if (!getstring(mail->subject)) exit(1);
if (stopped) {
free_mail(mail);
return;
}
}
strtrim(mail->subject);
if (!*mail->subject && level != MBOX) {
errors++;
puts("No subject specified.");
free_mail(mail);
return;
}
if (packetcluster || level != MBOX)
printf("Enter message for %s: (terminate with ^Z or ***END)\n",
mail->orig_to);
if (level != MBOX) {
sprintf(line,"de %s",mail->from);
append_line(mail,line);
sprintf(line,"to %s",mail->orig_to);
append_line(mail,line);
append_line(mail,"");
}
for (; ; ) {
if (!getstring(line)) exit(1);
if (!strncmp(line,"#BIN#",5)) {
#ifdef BOXBIN
mail->bin = 1;
i= send_binary(mail,line);
if( !i ) {
break ;
} else
if (i == 1)
{
mail->bin = 0;
} else
{
free_mail(mail);
return;
}
#else
puts("#NO#");
free_mail(mail);
return;
#endif
}
if (stopped) {
free_mail(mail);
return;
}
if (*line == '\032') break;
if (*line == '\001' && level != MBOX) {
free_mail(mail);
puts("aborted.");
return;
}
if (!Strncasecmp(line, "***end", 6)) break;
if (!(check_header && line[0] == ' ' && line[1] == '[')) {
append_line(mail, line);
if (check_header) {
if (p = get_host_from_header(line)) {
if (*path) strcat(path, "!");
strcat(path, p);
} else if (*path)
check_header = 0;
}
}
if (strchr(line, '\032')) break;
}
if (*path) {
strcpy(line, mail->from);
sprintf(mail->from, "%s!%s", path, line);
}
if (level != MBOX) printf("Sending message to %s.\n", mail->to);
route_mail(mail);
}
#undef nextarg
/*---------------------------------------------------------------------------*/
void set_command(int argc, char **argv)
{
int i,j;
char *errstr = "Syntax error. Type ? SET for help.";
if(argc == 1) {
printf("userinterface: ");
if (interface_type == wampes)
printf("wampes\n");
else
if (interface_type == diebox)
printf("DieBox\n");
else
printf("unknown\n");
if (interface_type == wampes) {
printf("prompt: %s\n",prompt);
printf("escape character: %d\n", escape_char);
#ifdef BOXBIN
printf("binary: %s\n", binary_allowed ? "yes" : "no");
#endif
printf("subject in send command : %sallowed\n",
subject_in_send ? "" : "not ");
printf("editor: %s\n", editor);
printf("list last messages: %d\n", max_list);
printf("fix address: %s\n", fix_allowed ? "yes" : "no");
}
if (level == ROOT) {
printf("compress-program: %s\n",compress);
printf("compress-extention: %s\n", compressext);
printf("uncompress-option: %s\n", uncompressoption);
printf("BBS-Administrator: %s\n", bbsadm);
printf("domain: %s\n", mydomain);
printf("hostname: %s\n", myhostname);
printf("station is: %s\n", station);
printf("debug mode: %s\n", (debug) ? "yes" : "no");
}
return ;
}
for (i=1; i < argc; i++) {
#ifdef BOXBIN
if (!Strncasecmp(argv[i],"binary",6) && (interface_type == wampes)) {
binary_allowed=1;
} else
#endif
if (!Strncasecmp(argv[i],"fixaddress",6) && (interface_type == wampes)) {
fix_allowed=1;
} else
if (!Strncasecmp(argv[i],"subject",6) && (interface_type == wampes)) {
subject_in_send=1;
} else
if (!Strncasecmp(argv[i],"editor",6) && (interface_type == wampes)) {
i++;
if (i == argc || *argv[i] != '=' ) {
printf("%s\n",errstr);
return;
}
if (++i == argc) {
printf("%s\n",errstr);
return;
}
strcpy(editor,argv[i]);
} else
if (!Strncasecmp(argv[i],"list",4) && (interface_type == wampes)) {
i++;
if (i == argc || *argv[i] != '=' ) {
printf("%s\n",errstr);
return;
}
if (++i == argc) {
printf("%s\n",errstr);
return;
}
max_list = atoi(argv[i]);
} else
if (!Strncasecmp(argv[i],"escape",6) && (interface_type == wampes)) {
i++;
if (i == argc || *argv[i] != '=' ) {
printf("%s\n",errstr);
return;
}
if (++i == argc) {
printf("%s\n",errstr);
return;
}
if (!isdigit(*argv[i])) {
printf("%s\n",errstr);
return;
}
escape_char=Atoi(argv[i]);
} else
if (!Strncasecmp(argv[i],"interface",6)) {
i++;
if (i == argc || *argv[i] != '=' ) {
printf("%s\n",errstr);
return;
}
if (++i == argc) {
printf("%s\n",errstr);
return;
}
if (!Strcasecmp(argv[i],"wampes")) {
strcpy(prompt,"bbsx> ");
escape_char = orig_escape;
binary_allowed = 0;
subject_in_send =0;
interface_type = wampes;
free(alias_table);
init_aliasdb();
} else
if (!Strcasecmp(argv[i],"diebox") || !Strcasecmp(argv[i],"thebox")) {
strcpy(prompt,"(\\w) \\u de \\h>");
escape_char = 10;
binary_allowed = 1;
subject_in_send = 1;
interface_type = diebox;
free(alias_table);
init_aliasdb();
insert_alias("CHECK","LIST NEW",0,1);
insert_alias("FORWARD","MAIL",0,1);
insert_alias("TRANSFER","MOVE",0,1);
insert_alias("!","__",255,1);
insert_alias("?","__",255,1);
insert_alias("DELETE","_DELETE",255,1);
insert_alias("DISCONNECT","_DISCONNECT",255,1);
insert_alias("EXIT","_EXIT",255,1);
insert_alias("INFO","_INFO",255,1);
insert_alias("KILL","_KILL",255,1);
insert_alias("MOVE","_MOVE",255,1);
insert_alias("PRINT","_PRINT",255,1);
insert_alias("RESPOND","_RESPOND",255,1);
insert_alias("SHELL","_SHELL",255,1);
insert_alias("SOURCE","_SOURCE",255,1);
insert_alias("STATUS","_STATUS",255,1);
insert_alias("TYPE","_TYPE",255,1);
insert_alias("UNERASE","_UNERASE",255,1);
insert_alias("UNSET","_UNSET",255,1);
insert_alias("VERSION","_VERSION",255,1);
insert_alias("WRITE","_WRITE",255,1);
insert_alias("ALIAS","_ALIAS",255,1);
} else
{
printf("%s\n",errstr);
return;
}
} else
if (!Strcasecmp(argv[i],"prompt") && (interface_type == wampes)) {
i++;
if (i == argc || *argv[i] != '=' ) {
printf("%s\n",errstr);
return;
}
if (++i == argc) {
printf("%s\n",errstr);
return;
}
*prompt=0;
for(j=i; j < argc; j++) {
strcat(prompt,argv[j]);
}
} else {
printf("What should I set ?\n");
return;
}
}
return;
}
/*---------------------------------------------------------------------------*/
void sid_command(int argc, char **argv)
{
#define DELIM "[]-"
int i;
char box_soft[16];
char soft_ver[16];
char flags[16];
char password[20];
char *f, *t, *s;
char buf[1024];
FILE *dbfp;
FILE *pwdfp;
f = argv[1];
*box_soft = 0;
*soft_ver = 0;
*flags = 0; *buf = 0;
s=buf;
for(;;) {
if (!*f) break;
t=s;
while (*f && !strchr(DELIM, *f)) *t++ = *f++;
*t++ = 0;
if (!*box_soft)
strcpy(box_soft, buf);
else
if (strchr(buf, '$'))
strcpy(flags, buf);
else
if(!*soft_ver)
strcpy(soft_ver, buf);
if (*f) f++;
}
if (argc > 3)
strcpy(password, argv[3]);
if (argc > 3) {
if (doforward) {
if (!get_passwd(user.name, password, boxpassword )) exit (0);
password_ok = 1;
}
else {
if (strcmp(boxpassword, password)) exit (0);
password_ok = 1;
}
}
if (!Strcasecmp(box_soft,"thebox")) {
if (!strcmp("1.9",soft_ver)) {
binary_allowed = 1;
subject_in_send = 1;
}
if (!strcmp("1.8",soft_ver)) {
subject_in_send = 1;
}
} else
if (!Strcasecmp(box_soft,"baycom")) {
if (!strcmp("1.14",soft_ver)) {
subject_in_send = 1;
}
if (!strcmp("1.15",soft_ver)) {
subject_in_send = 1;
}
}
return;
}
/*---------------------------------------------------------------------------*/
void source_command(int argc, char **argv)
{
FILE *fp;
char line[1024];
sprintf(line, "%s/%s", user.dir, argv[1]);
if (fp = fopen(line, "r")) {
while (fgets(line, sizeof(line), fp)) parse_command_line(line);
fclose(fp);
} else
printf("can't open open file: %s\n",argv[1]);
return;
}
/*---------------------------------------------------------------------------*/
void status_command(int argc, char **argv)
{
int active = 0;
int crunchok = 0;
int deleted = 0;
int highest = 0;
int n;
int new = 0;
int readable = 0;
long validdate;
struct index *pi, index[1000];
validdate = time((long *) 0) - 90 * DAYS;
printf("BBSX Revision: %s %s\n", BBSX_REVISION, REVISION_DATE);
printf("BBSX based on DK5SG-BBS\n");
if (lseek(fdindex, 0L, SEEK_SET)) halt();
for (; ; ) {
n = read(fdindex, pi = index, 1000 * sizeof(struct index)) / sizeof(struct index);
if (n < 1) break;
for (; n; n--, pi++) {
highest = pi->mesg;
if (pi->flags & DELETED) {
deleted++;
if (!*pi->bid || pi->date < validdate) crunchok++;
} else {
active++;
if (read_allowed(pi)) {
readable++;
if (pi->mesg > user.seq) new++;
}
}
}
}
printf("%6d Highest message number\n", highest);
printf("%6d Active messages\n", active);
printf("%6d Readable messages\n", readable);
if (level == ROOT) {
printf("%6d Deleted messages\n", deleted);
printf("%6d Messages may be crunched\n", crunchok);
}
printf("%6d Last message listed\n", user.seq);
printf("%6d New messages\n", new);
}
/*---------------------------------------------------------------------------*/
void tell_command(int argc, char **argv)
{
char *errstr = "Syntax Error. Type ? TELL for help.\n";
char at[1024];
struct mail *mail;
int i;
mail = alloc_mail();
*at = 0;
if (argc < 3) {
puts(errstr);
free_mail(mail);
return;
}
if (!callvalid(get_host_from_path(argv[1])) ||
strlen(argv[1]) < 4 ) {
printf("Invalid Call: %s\n",argv[1]);
free_mail(mail);
return;
}
strcpy(mail->to,"T");
strcpy(at,argv[1]);
strcat(mail->to, "@");
strcat(mail->to, at);
strlwc(mail->to);
strcpy(mail->orig_to, mail->to);
strcpy(mail->from, user.name);
if (*mail->bid) {
mail->bid[LEN_BID] = 0;
strupc(mail->bid);
if (!msg_uniq(mail->bid, mail->mid)) {
puts("No");
free_mail(mail);
return;
}
}
strcpy(mail->subject,argv[2]);
for(i=3;i < argc; i++) {
strcat(mail->subject," ");
strcat(mail->subject,argv[i]);
}
printf("Tell is asking %s for command: %s\n", argv[1], mail->subject);
strcat(mail->subject," @ ");
strcat(mail->subject, Myhostname);
route_mail(mail);
}
/*---------------------------------------------------------------------------*/
void undelete_command(int argc, char **argv)
{
int i;
int mesg;
struct index index;
int max_mesg;
int found = 0;
max_mesg = get_highest_mesg(argc,argv);
for (mesg = get_lowest_mesg(argc,argv); mesg <= max_mesg; mesg++)
if (mesg_in_command(argc, argv, mesg, &index) &&
!(index.flags & DELETED) &&
strcmp(index.to,"B")) {
found = 1;
if (level == ROOT ||
calleq(index.from, user.name)) {
index.date = time((long *) 0);
strcpy(index.to,index.orig_to);
getalias(index.to);
if (lseek(fdindex, -sizeof(struct index), SEEK_CUR) < 0) halt();
if (write(fdindex, &index, sizeof(struct index)) !=
sizeof(struct index)) halt();
printf("Message %d undeleted.\n", mesg);
} else
printf("Message %d not undeleted: Permission denied.\n", mesg);
}
if (!found) {
printf("No message found.\n");
}
return;
}
/*---------------------------------------------------------------------------*/
void unknown_command(int argc, char **argv)
{
errors++;
printf("Unknown command '%s'. Type ? for help.\n", *argv);
}
/*---------------------------------------------------------------------------*/
void unset_command(int argc, char **argv)
{
int i;
for (i=1; i < argc; i++) {
#ifdef BOXBIN
if (!Strncasecmp(argv[i],"binary",6))
binary_allowed=0;
else
#endif
if (!Strncasecmp(argv[i],"subject",6))
subject_in_send=0;
else
if (!Strncasecmp(argv[i],"fixaddress",6))
fix_allowed=0;
else
printf("There is no %s to unset.\n",argv[i]);
}
return;
}
/*---------------------------------------------------------------------------*/
void write_command(int argc, char **argv)
{
int fp, wfp;
char buffer[1024];
char filename[512];
int rd, wr;
int mesg;
struct index index;
int i;
int max_mesg;
int found = 0;
int bytes = 0;
struct tm *tm;
long now;
char logfile[80];
struct log log;
now = time(0L);
tm=gmtime(&now);
sprintf(logfile,"%s%02d%02d.log",LOGFILE,tm->tm_year, tm->tm_mon);
if (argc < 3) {
printf("Syntax error. Type ? WRITE for help.\n");
return;
}
strcpy(filename,user.dir);
strcat(filename,"/");
strcat(filename,argv[1]);
for (i = 2; i < argc; i++)
if ((mesg = Atoi(argv[i])) > 0 && get_index(mesg, &index) &&
read_allowed(&index)) {
found = 1;
bytes = 0;
if (!(wfp = open(filename, O_APPEND | O_WRONLY | O_CREAT, 0644))) halt();
if (!(fp = open(getfilename(mesg), O_RDONLY))) halt();
sprintf(buffer,"\nMsg# %d To: %s%s%s From: %s Date: %s\n",
index.mesg,
index.to,
*index.at ? " @" : "",
index.at,
index.from,
timestr(index.date));
write(wfp,buffer,strlen(buffer));
if (*index.subject) sprintf(buffer,"Subject: %s\n", index.subject);
write(wfp,buffer,strlen(buffer));
if (*index.bid) sprintf(buffer,"Bulletin ID: %s\n", index.bid);
write(wfp,buffer,strlen(buffer));
do {
rd=read(fp, buffer, 1024);
wr=write(wfp, buffer, rd);
bytes += rd;
if (wr != rd) halt();
} while (rd);
close(wfp);
close(fp);
if (chown(filename, user.uid, user.gid)) halt() ;
printf("wrote message %d to %s\n", mesg, filename);
if(log_reading && bytes && level == USER) {
strcpy(log.to, index.to);
log.bytes=bytes;
log.uid = user.uid;
log.time = time(0L);
if ((fdlog = lock_file(LOCKFILE, 0)) < 0) halt();
if (lseek(fdlog, 0L, SEEK_END) < 0) halt();
if (write(fdlog, &log, sizeof(struct log)) != sizeof(struct log)) halt();
close(fdlog);
}
}
else
printf("No such message: '%s'.\n", argv[i]);
if (!found) {
printf("No message found.\n");
}
return;
}
/*---------------------------------------------------------------------------*/
void xcrunch_command(int argc, char **argv)
{
#define TEMP_BID_DB BID_DB ".tmp"
#define TEMP_INDEXFILE INDEXFILE ".tmp"
DBM * bid_db;
datum datum_bid;
datum datum_offset;
int f;
int wflag;
long offset;
long validdate;
struct index index;
validdate = time((long *) 0) - 90 * DAYS;
if ((f = open(TEMP_INDEXFILE, O_WRONLY | O_CREAT | O_EXCL, 0644)) < 0) halt();
if (lseek(fdindex, 0L, SEEK_SET)) halt();
if (!(bid_db = dbm_open(TEMP_BID_DB, O_RDWR | O_CREAT, 0644))) halt();
offset = 0;
wflag = 0;
while (read(fdindex, &index, sizeof(struct index)) == sizeof(struct index)) {
wflag = 1;
if (!(index.flags & DELETED) || *index.bid && index.date >= validdate) {
if (write(f, &index, sizeof(struct index)) != sizeof(struct index)) halt();
wflag = 0;
if (*index.bid && index.date >= validdate) {
datum_bid.dptr = index.bid;
datum_bid.dsize = strlen(index.bid);
datum_offset.dptr = (char *) &offset;
datum_offset.dsize = sizeof(offset);
if (dbm_store(bid_db, datum_bid, datum_offset, DBM_REPLACE) < 0) halt();
}
offset += sizeof(struct index);
}
}
if (wflag)
if (write(f, &index, sizeof(struct index)) != sizeof(struct index)) halt();
if (close(f)) halt();
dbm_close(bid_db);
if (close(fdindex)) halt();
if (rename(TEMP_INDEXFILE, INDEXFILE)) halt();
if (rename(TEMP_BID_DB ".db", BID_DB ".db")) {
if (rename(TEMP_BID_DB ".dir", BID_DB ".dir")) halt();
if (rename(TEMP_BID_DB ".pag", BID_DB ".pag")) halt();
}
exit(0);
}
/*---------------------------------------------------------------------------*/
#define Invalid ( \
(pi->flags & DELETED) || \
*from && strcmp(pi->from, from) || \
*to && strcmp(pi->to, to) || \
*at && strcmp(pi->at, at) || \
*subject && !strcasepos(pi->subject, subject) \
)
void xscreen_command(int argc, char **argv)
{
FILE *fp = 0;
char at[1024];
char buf[1024];
char from[1024];
char subject[1024];
char to[1024];
int cmd;
int indexarrayentries;
int lines = 0;
int maxlines;
int mesg;
struct index *indexarray;
struct index *pi;
struct stat statbuf;
struct termios curr_termios, prev_termios;
unsigned int indexarraysize;
if (fstat(fdindex, &statbuf)) halt();
indexarraysize = statbuf.st_size;
indexarrayentries = indexarraysize / sizeof(struct index);
if (!indexarrayentries) return;
if (!(indexarray = malloc(indexarraysize))) halt();
if (lseek(fdindex, 0L, SEEK_SET)) halt();
if (read(fdindex, indexarray, indexarraysize) != indexarraysize) halt();
tcgetattr(0, &prev_termios);
curr_termios = prev_termios;
curr_termios.c_iflag = BRKINT | ICRNL | IXON | IXANY | IXOFF;
curr_termios.c_lflag = 0;
curr_termios.c_cc[VMIN] = 1;
curr_termios.c_cc[VTIME] = 0;
tcsetattr(0, TCSANOW, &curr_termios);
if (!(maxlines = Atoi(getenv("LINES")))) maxlines = 24;
*from = *to = *at = *subject = 0;
pi = indexarray;
cmd = '\b';
for (; ; ) {
lines = 0;
fflush(stdout);
while (!cmd) cmd = getchar();
switch (cmd) {
case '\b':
if (pi > indexarray) pi--;
while (Invalid && pi > indexarray) pi--;
while (Invalid && pi < indexarray + (indexarrayentries - 1)) pi++;
cmd = Invalid ? 'q' : 'r';
break;
case 'k':
if (unlink(getfilename(pi->mesg))) halt();
pi->flags = pi->flags | DELETED;
if (lseek(fdindex, (pi - indexarray) * sizeof(struct index), SEEK_SET) < 0) halt();
if (write(fdindex, pi, sizeof(struct index)) != sizeof(struct index)) halt();
case '\n':
if (pi < indexarray + (indexarrayentries - 1)) pi++;
while (Invalid && pi < indexarray + (indexarrayentries - 1)) pi++;
while (Invalid && pi > indexarray) pi--;
cmd = Invalid ? 'q' : 'r';
break;
case 'r':
if (fp) {
fclose(fp);
fp = 0;
}
if (!(fp = fopen(getfilename(pi->mesg), "r"))) halt();
printf("\033&a0y0C\033JMsg# %d To: %s%s%s From: %s Date: %s\n", pi->mesg, pi->to, *pi->at ? " @" : "", pi->at, pi->from, timestr(pi->date));
lines++;
if (*pi->subject) {
printf("Subject: %s\n", pi->subject);
lines++;
}
if (*pi->bid) {
printf("Bulletin ID: %s\n", pi->bid);
lines++;
}
putchar('\n');
lines++;
case ' ':
if (fp) {
while (lines < maxlines - 1 && fgets(buf, sizeof(buf), fp)) {
fputs(buf, stdout);
lines++;
}
if (feof(fp)) {
fclose(fp);
fp = 0;
}
cmd = 0;
} else
cmd = '\n';
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
tcsetattr(0, TCSANOW, &prev_termios);
printf("\nMessage number: %c", cmd);
*buf = cmd;
gets(buf + 1);
tcsetattr(0, TCSANOW, &curr_termios);
mesg = Atoi(buf);
pi = indexarray;
while ((mesg > pi->mesg || Invalid) && pi < indexarray + (indexarrayentries - 1)) pi++;
while (Invalid && pi > indexarray) pi--;
cmd = Invalid ? 'q' : 'r';
break;
case '<':
*from = *to = *at = *subject = 0;
tcsetattr(0, TCSANOW, &prev_termios);
printf("\nFROM field: ");
gets(from);
tcsetattr(0, TCSANOW, &curr_termios);
strupc(from);
cmd = Invalid ? '\n' : 'r';
break;
case '>':
*from = *to = *at = *subject = 0;
tcsetattr(0, TCSANOW, &prev_termios);
printf("\nTO field: ");
gets(to);
tcsetattr(0, TCSANOW, &curr_termios);
strupc(to);
cmd = Invalid ? '\n' : 'r';
break;
case '@':
*from = *to = *at = *subject = 0;
tcsetattr(0, TCSANOW, &prev_termios);
printf("\nAT field: ");
gets(at);
tcsetattr(0, TCSANOW, &curr_termios);
strupc(at);
cmd = Invalid ? '\n' : 'r';
break;
case 's':
*from = *to = *at = *subject = 0;
tcsetattr(0, TCSANOW, &prev_termios);
printf("\nSUBJECT substring: ");
gets(subject);
tcsetattr(0, TCSANOW, &curr_termios);
cmd = Invalid ? '\n' : 'r';
break;
case 'v':
sprintf(buf, "%s %s", editor, getfilename(pi->mesg));
tcsetattr(0, TCSANOW, &prev_termios);
system(buf);
tcsetattr(0, TCSANOW, &curr_termios);
cmd = 'r';
break;
case 'q':
tcsetattr(0, TCSANOW, &prev_termios);
free(indexarray);
return;
case '?':
puts("----------------------------------- Commands ----------------------------------");
puts("< specify FROM field");
puts("<number> show numbered entry");
puts("> specify TO field");
puts("? print command summary");
puts("@ specify AT field");
puts("BACKSPACE show previous entry");
puts("RETURN show next entry");
puts("SPACE show next screenful");
puts("k delete current entry");
puts("q quit screen mode");
puts("r redisplay current entry");
puts("s specify SUBJECT substring");
puts("v edit current entry");
printf("\nPress any key to continue ");
getchar();
cmd = 'r';
break;
default:
putchar('\007');
cmd = 0;
break;
}
}
}
#undef Invalid